<?php
/*
    Words

    Good words. 
        Spelling is approved. 
        Will not be flagged.
        File list.

    Bad words.
        Will always be flagged.
        Prevented from entry to Good Words.
        File list.

    Check words.
        Aspell rejects.
        Plus Bad words.
        Minus Good words.
        Can be proved (if not Bad)

    Suggested words.
        Good words that haven't been approved yet.
        Stored with Good words but ignored until approved.
        May be rejected as Good - permanently ignored.

    Wordcheck
        Flags Check words.
            a. Approvable = not Bad
            b. Not approvable = Bad
*/

public function SpellCheckRejects($langcode = null)
{

    if(! $langcode)
        $langcode = $this->FirstLanguageCode();
    return $this->do_aspell($langcode);
}

    // options:
    // ignore-case
    // lang
    // language-tag
    // sug-mode (ultra)
    // personal (personal word list filename)
    // repl (replacements file name)

    // master, -d main dictionary
    // dict-dir
    // extra-dicts
    // strip-accents
    // run-together, -C or -B
    // run-together-limit   # words limit
    // run-together-min     min subword length

public function do_aspell($langcode = null)
{
    global $charset;
    global $aspell_temp_dir;
    global $aspell_executable;
    global $aspell_prefix;
    global $Context;

    if(empty($langcode))
        $langcode = $Context->DefaultLocale();
    $dfile = build_path($aspell_prefix,
                        left($langcode, 2).".multi");
    // $dpath = build_path($aspell_prefix, $langcode.".multi");
    // assert(is_file($dpath));
    $temp_text_path = build_path(TEMP_ROOT, 
                            $this->ProjectId()."_wc.txt");        
    // say($temp_text_path);
    file_put_contents($temp_text_path, $this->Text());

    $cmd = "cat $temp_text_path "
          ." | "
          ." $aspell_executable"
          ." list"
          ." --ignore-case"
          ." --prefix=$aspell_prefix"
          ." -d $dfile"
          ." --encoding $charset"
          ." | tr '[:upper:]' '[:lower:]'"
          ." | sort"
          ." | uniq -c"
          ." | sort -k 1nr -k 2";


    // say($cmd);
    $rejects = `$cmd`;
    unlink($temp_text_path);
    return $rejects;
}

public function SpellCheckRejectsArray($langcode = null)
{
    $rejects = $this->SpellCheckRejects($langcode);
    $arejects = preg_split("/\s+/", $rejects);
    return $arejects;
}

public function GoodWords($langcode = null)
{
    static $_good_words = array();
    if(is_null($langcode))
        $langcode = $this->FirstLanguageCode();

    if( isset($_good_words[$langcode]))
        return $_good_words[$langcode];

    if(! is_file($this->GoodWordsFilePath($langcode)))
    {
        $_good_words[$langcode] = array();
        return $this->_good_words[$langcode];
    }
    $this->_good_words[$langcode] 
            =  file_get_contents(
                        $this->GoodWordsFilePath($langcode));
    return $this->_good_words[$langcode];
}

public function BadWords($langcode = null)
{
    static $_bad_words = array();
    if(! $langcode)
        $langcode = $this->FirstLanguageCode();
    if(isset($_bad_words[$langcode]))
        return $_bad_words[$langcode];

    if(! is_file($this->BadWordsFilePath($langcode)))
    {
        $_bad_words[$langcode] = array();
        return $_bad_words[$langcode];
    }

    $_bad_words[$langcode] 
            =  file_get_contents(
                        $this->BadWordsFilePath($langcode));
    return $_bad_words[$langcode];
}

public function PossibleBadWordsCount()
{
    return 0;
}

public function ActivePageWordInstances($word)
{
    $text = $this->ActivePageText();
    $pattern = "/\b".$word."\b/";
    return text_matches_with_offsets($pattern, $text);
}

private function project_matches_with_offsets($pattern)
{
    return text_matches_with_offsets($pattern, $this->Text());
}

private function text_matches_with_offsets($pattern, $text)
{
    $n = preg_match_all($pattern, 
                $text, $matches, PREG_OFFSET_CAPTURE);
    // var_dump($matches[0]);
    $ary = array();
    foreach($matches[0] as $wd => $offset)
    {
        $ary[$wd] = $offset;
    }
    return $ary;
}

public function WordInstances($word)
{
    $ptn = "/\b".$word."\b/";
    return $this->project_matches_with_offsets($ptn);
}

private function PageTextLines($pg)
{
    $text = PageText($pg);
    $lines = preg_split("/\n/", $text);
    return $lines;
}

public function OffsetContext($offset)
{
    say($offset);
    $pg = $this->PageForOffset($offset);
    var_dump($pg);
    $pgtext = $this->PageText($pg);
    say($pgtext);
    die();
    $ptr1 = mb_strrpos($pgtext, "\n", $offset - $pg->Offset());
    $ptr2 = mb_strpos($pgtext, "\n", $offset - $pg->Offset());
    return substr($pgtext, $ptr1+1, $ptr2-1);
}

private function PageForOffset($offset)
{
    foreach($this->_page_texts as $pt)
    {
        if($pt->Offset() <= $offset)
            return $pt;
    }
    return null;
}

class DpProjectWords
{
    private $_projectid;
    public function __construct($projectid)
    {
        $this->_projectid = $projectid;
    }

    public function WordsTypeArray($projectid, $wordstype)
    {
        return is_file($this->WordsPath($wordstype))
            ? file_get_contents($this->WordsTypePath($wordstype))
            : array();
    }

    public function SaveWords($wordstype)
    {
    }

    public function SuggestedWordsArray()
    {
        return $this->WordsTypeArray("suggested");
    }

public function SaveSuggestedWords($words)
{
    $this->SaveWordsType($words, $wordstype)
    {
        file_put_contents($words $this->WordsTypePath($wordstype);
    }
}

public function WordsTypeFileName($wordstype)
{
    return  "_".$wordstype.".words";
}

public function WordsTypePath($wordstype)
{
    return build_path($this->ProjectPath(), 
                $this->WordsTypeFileName($wordstype));
}

public function WordsTypeArray($wordstype)
{
    return preg_split("/\s+/", $this->TypeWords($wordstype));
}

public function WordsTypeFileUrl($wordstype)
{
    return build_path($this->ProjectUrl(), 
                    $this->WordsTypeFileName($wordstype));
}

public function GoodWordsFilePath()
{
    return $this->WordsTypeFilePath(GOOD):
}

public function GoodWordsFileUrl()
{
    return $this->WordsTypeFileUrl(GOOD);
}

public function BadWordsFilePath()
{
    return $this->WordsTypeFilePath(BAD);
}

public function BadWordsFileUrl()
{
    return $this->WordsTypeFileUrl(BAD);
}

public function GoodWordsModifiedTime()
{
    return $this->WordsTypeModifiedTime(GOOD);
}

public function WordsTypeModifiedTime($wordstype)
{
    return is_file($this->WordsTypeFilePath($wordstype))
        ?  filemtime($this->WordsTypeFilePath($wordstype))
        : null;
}

public function BadWordsModifiedTime()
{
    return $this->WordsTypeModifiedTime(BAD);
}

public function GoodWordsArray()
{
    return $this->WordsTypeArray(GOOD);
}

public function BadWordsArray()
{
    return $this->WordsTypeArray(BAD);
}

public function WordsTypeArray($wordstype)
{
    return preg_split("/\s+/", $this->TypeWords(wordstype));
}

public function SaveWordsType($words, $wordstype)
{
    $this->SaveWordsToFile($words,
        $this->WordsTypeFilePath($wordstype);
}

public function SaveBadWords($words)
{
    $this->SaveWordsType($words, BAD);
}

public function SaveGoodWords($words)
{
    $this->SaveWordsType($words, GOOD);
}

}

class DpProjectWordInstance
{
    private $_projectid;
    private $_pagename;
    private $_text;
    private $_imagepath;
    private $_index;
    private $_offset;
    private $_len;

    public function __construct($projectid, $text, $pagename,
                                        $offset, $imagepath)
    {
        $this->_projectid = $projectid;
        $this->_text = $text;
        $this->_pagename = $pagename;
        $this->_offset = $offset;
        $this->_imagepath = $imagepath;
    }

    public function Offset()
    {
        return $this->_offset;
    }

    public function Length()
    {
        return mb_strlen($this->_text);
    }

    public function PageName()
    {
        return $this->_pagename;
    }

    public function ImagePath()
    {
        return $this->_imagepath;
    }
}

class DpWord
{
private $_val;
private $_instcount = null;

public function __construct($val, $instcount = null)
{
    $this->_val = $val;
    $this->_instcount = $instcount;
}

function ToString()
{
    return $_val;
}
}

class DpLangWords extends ArrayObject
{
function __construct(&$array, $langcode = null,
                    $projectid = null, $wordstype = null)
{
}
}

function language_dictionary_path($langcode)
{
global $aspell_prefix;
return build_path($aspell_prefix, $langcode.".multi");
}
?>
